/* oscillators.cu
 - basic ocsillators running over GPU.
 */

#ifdef __CDT_PARSER__
#define __global__
#define __device__
#define __host__
#define __shared__

#define CUDA_KERNEL_DIM(...)

#else
#define CUDA_KERNEL_DIM(...)  <<< __VA_ARGS__ >>>

#endif

#include <cuda.h>
#include <cutil.h>

#include <math_functions.h>

#include <iostream>
#include <math.h>
#include <time.h>

#include "oscillators.h"
#include "globals.h"

using namespace std;

#define SIN(ph0, freq, gain, offset) \
	(offset + ( gain * sin(ph0 + (phase * freq) ) ) )

#define SAW(ph0, phase, freq, gain, offset) \
		(offset-0.5+(gain*((2*M_PI-((ph0 + (phase*freq))) / ((float)2*M_PI)))))

struct osc_params {
	// all values range from 0.0 - 1.0
	float ph0;
	float freq;
	float gain;
	float offset;
};

int threadsPerBlock = 64;

__device__ float saw(float ph0, float phase, int freq, float gain, float offset) {
	int t = floor(phase*freq/((float)M_PI*2));
	float _phase = (phase*freq) - (M_PI*t*2);
	return offset + (gain*(((2*M_PI)-_phase) / ((float)2*M_PI)));
}

__global__ void instrument1(float *buf_d, int sidx, float _phase, float ph0,
		float freq, float gain, float offset) {
	int idx = blockIdx.x * blockDim.x + threadIdx.x;
	float phase = (sidx + idx)* _phase;
//	buf_d[idx] = gain * sinf(ph0 + (phase * (f_invscale(freq))));
	buf_d[idx] = SIN( SIN(ph0, 1, 10, 0),
			400,
			1,
			0);
//	(0 + ( 1 * sin((0 + ( 10 * sin(ph0 + (phase * 1) ) ) ) + (phase * 400) ) ) )
}

void synthesiser_dispatch(float *buf_d, int N, int sidx) {
	float _phase = 2 * M_PI / SAMPLE_RATE;
	unsigned int numBlocks = (N + threadsPerBlock - 1) / threadsPerBlock;
	instrument1 <<<numBlocks, threadsPerBlock >>>
	(	buf_d, sidx, _phase, 0,
		f_scaled(700), 1, 0
	);
}
